/**
 * File:   lcd_stm32_raw.c
 * Author: AWTK Develop Team
 * Brief:  stm32_raw implemented lcd interface
 *
 * Copyright (c) 2018 - 2018  Guangzhou ZHIYUAN Electronics Co.,Ltd.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * License file for more details.
 *
 */

/**
 * History:
 * ================================================================
 * 2018-02-16 Li XianJing <xianjimli@hotmail.com> created
 *
 */

#include <stdint.h>
#include "stdlib.h"
#include "lcdsim.h"

#include "tkc/mem.h"
#include "base/lcd.h"
#include "lcd/lcd_mem_rgb565.h"

#ifdef LCD_USE_TRIPLE_BUFFER
static uint8_t *s_next_fb = NULL;
static uint8_t *s_online_fb = NULL;
static lcd_begin_frame_t org_begin_frame;

ret_t lcd_win_begin_frame(lcd_t *lcd, rect_t *dirty_rect)
{
    uint8_t *iter;
    
    if (lcd_is_swappable(lcd))
    {
        uint32_t i = 0;
        lcd_mem_t *mem = (lcd_mem_t *)lcd;

        mem->next_fb = NULL;
        mem->online_fb = NULL;
        mem->offline_fb = NULL;
        for (i = 0; i < ARRAY_SIZE(frameBuffer); i++)
        {
            iter = (uint8_t*)&frameBuffer[i];
            if (iter != s_online_fb && iter != s_next_fb)
            {
                mem->offline_fb = iter;
                break;
            }
        }

        org_begin_frame(lcd, dirty_rect);
    }

    return RET_OK;
}

ret_t lcd_win_swap(lcd_t *lcd)
{
    lcd_mem_t *mem = (lcd_mem_t *)lcd;

    s_next_fb = mem->offline_fb;

    return RET_OK;
}

//Frame Display Complete Interrupt
void *lcd_fdc_callback(void)
{
    if (s_next_fb != NULL)
    {
        s_online_fb = s_next_fb;
        s_next_fb = NULL;

		return(s_online_fb);
    }

	return NULL;
}
#endif

lcd_t *win_create_lcd(wh_t w, wh_t h)
{
    lcd_t *lcd = NULL;

    #ifdef LCD_USE_TRIPLE_BUFFER
    lcd = lcd_mem_rgb565_create_three_fb(w, h, (uint8_t *)&frameBuffer[0], (uint8_t *)&frameBuffer[1], (uint8_t *)&frameBuffer[2]);
    
    org_begin_frame = lcd->begin_frame;
    lcd->swap = lcd_win_swap;
    lcd->begin_frame = lcd_win_begin_frame;
    #else
    lcd = lcd_mem_bgr565_create_single_fb(w, h, (uint8_t *)&frameBuffer[0]);
    #endif
    
    return lcd;
}

